package com.lnt.java.thread;

import com.lnt.java.thread.safe.*;

public class ThreadDemoTest {

    public static void main(String[] args) {
//        threadTicketTest();
        /* 为什么会出现线程不安全的问题：
            1.当多线程并发访问临界资源时，如果破坏原子操作，可能造成数据不一致
            2.临界资源：共享资源(同一对象),一次仅允许一个线程做操作，才能保证其正确性
            3.原子操作：不可分割的多步步骤，被视为一个整体，其顺序和步骤是不可以被打乱的
         */
        /*
        线程安全问题都是由全局变量或者静态变量引起的，若每个线程对全局变量或者静态变量只有读的操作，一般来说，这个全局变量是安全的
        如果多个线程对全局变量执行写操作，一般都需要考虑线程同步，否则会导致线程不安全
         */
        // 解决方法
        // 1.同步代码块
//        threadSafeSynchornized();
        // 2.同步方法
//        treadSafeSynchornizedMethodTest1();
        // 3. 不加Lock的情况下
//        treadSafeUnLockTest1();
        // 加上lock 之后
        treadSafeLockTest2();
    }


    private static void threadTicketTest () {
        // 测试线程安全的方法
        // 启动三个线程去执行
        Ticket ticket = new Ticket();
        Thread t1 = new Thread(ticket, "用户A");
        Thread t2 = new Thread(ticket, "用户B");
        Thread t3 = new Thread(ticket, "用户C");
        t1.start();
        t2.start();
        t3.start();
        System.out.println("此时线程是不安全的");
    }

    private static void threadSafeSynchornizedBlaakTest1() {
        // 利用同步代码块来实现线程安全
        TicketSafeSynchronizedBlaakTest ticket = new TicketSafeSynchronizedBlaakTest();
        Thread t1 = new Thread(ticket, "用户A");
        Thread t2 = new Thread(ticket, "用户B");
        Thread t3 = new Thread(ticket, "用户C");
        t1.start();
        t2.start();
        t3.start();
    }

    private static void treadSafeSynchornizedMethodTest1() {
//        TicketSafeSynchronizedMethodTest ticket1 = new TicketSafeSynchronizedMethodTest();
//        TicketSafeSynchronizedMethodTest ticket2 = new TicketSafeSynchronizedMethodTest();
//        TicketSafeSynchronizedMethodTest ticket3 = new TicketSafeSynchronizedMethodTest();
//        Thread t1 = new Thread(ticket1, "用户A");
//        Thread t2 = new Thread(ticket2, "用户B");
//        Thread t3 = new Thread(ticket3, "用户C");
        TicketSafeSynchronizedMethodTest ticket1 = new TicketSafeSynchronizedMethodTest();
        Thread t1 = new Thread(ticket1, "用户A");
        Thread t2 = new Thread(ticket1, "用户B");
        Thread t3 = new Thread(ticket1, "用户C");

        t1.start();
        t2.start();
        t3.start();
    }

    private static void treadSafeUnLockTest1() {
        TicketSafeLockTest1 lock = new TicketSafeLockTest1();
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                lock.addStrArray("hello");
            }
        };
        Runnable r2 =  new Runnable() {
            @Override
            public void run() {
                lock.addStrArray("world");
            }
        };
        Thread t1 = new Thread(r1, "用户A");
        Thread t2 = new Thread(r2, "用户B");
        t1.start();
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String[] strArray = lock.getStrArray();
        for (String str : strArray) {
            System.out.println(str);
        }
    }

    private static void treadSafeLockTest2() {
        TicketSafeLockTest2 lock = new TicketSafeLockTest2();
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                lock.addStrArray("hello");
            }
        };
        Runnable r2 =  new Runnable() {
            @Override
            public void run() {
                lock.addStrArray("world");
            }
        };
        Thread t1 = new Thread(r1, "用户A");
        Thread t2 = new Thread(r2, "用户B");
        t1.start();
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String[] strArray = lock.getStrArray();
        for (String str : strArray) {
            System.out.println(str);
        }
    }
}
